package com.helloandroid.models

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.helloandroid.AppUtil
import com.helloandroid.app.model.AppCache
import com.helloandroid.ext.ParseResult
import com.helloandroid.tools.Http.asyncHttpReq
import com.helloandroid.tools.MyLog
import com.helloandroid.tools.MyTimeUtils
import com.helloandroid.vo.IDeepCopy
import dai.android.util.AndroidUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.lang.Exception

data class BsRecord(val daiTimeInt:Int,val target:Int,val bs:Int):IDeepCopy<BsRecord>,Comparable<BsRecord>{
    override fun deepCopy(): BsRecord {
        return this.copy()
    }

    override fun toString(): String {
        return "daiTimeInt:${daiTimeInt},target:${target},bs:${bs}"
    }

    override fun compareTo(other: BsRecord): Int {
        return daiTimeInt - other.daiTimeInt
    }
}

class BsRecordViewModel : ViewModel() {

    private fun parse(jsonStr:String):ParseResult{
        try {
            val jsonObj = JSONObject(jsonStr)
            val err = jsonObj.getInt("err")
            if (err == 0){
                val lst = ArrayList<BsRecord>()
                val infos = jsonObj.getJSONArray("data")
                for(i in 0 until infos.length()){
                    val item = infos.getJSONObject(i)
                    val bushuday = item.getString("bushuday")
                    if (bushuday == "null"){
                        continue
                    }
                    val bs = item.getInt("bushu")
                    val bsTarget = item.getInt("bsTarget")
                    lst.add(BsRecord(MyTimeUtils.simpleDayTimeStringToInt(bushuday),bsTarget,bs))
                }
                return ParseResult(err,lst)
            }else{
                return ParseResult(err,jsonObj.getString("msg"))
            }
        }catch (e:Exception){
            return ParseResult(1000, "解析错误")
        }
    }

    fun getInfo(callback:(Boolean,ArrayList<BsRecord>?)->Unit){
        val records = AppCache.copyBsRecords()
        if (records != null){
            callback(true,records)
            return
        }

        if (!AndroidUtils.networkConnected(AppUtil.app)){
            AppUtil.toast("请打卡网络!")
            callback(false,null)
            return
        }

        viewModelScope.launch {
            val jsonStr = asyncHttpReq("user/bushu/doc?user_id=${AppUtil.user.user_id}")

            // 由于这里 data 字段是一个数组. 这里自行解析
            val parseResult = parse(jsonStr)
            if (parseResult.err == 0){
                val lst = parseResult.obj as ArrayList<BsRecord>
                AppCache.bsRecords = lst
                callback(true,AppCache.copyBsRecords())
            }else{
                MyLog.info("err:${parseResult.err},msg:${parseResult.obj as String}")
                callback(false,null)
            }
        }
    }

    fun fill(lst: ArrayList<BsRecord>,dstLst:ArrayList<BsRecord>,callback:()->Unit){
        viewModelScope.launch {
            val def = async(Dispatchers.Default){
                fillList(lst,dstLst)
            }
            def.await()
            callback()
        }
    }

    private fun fillList(lst: ArrayList<BsRecord>,dstLst:ArrayList<BsRecord>): ArrayList<BsRecord> {

        // 为了安全起见 还是自己排个序
        lst.sort()

        dstLst.clear()
        val finalLst = dstLst

        val startInt = lst[0].daiTimeInt
        var preTarget = lst[0].target
        val endInt = lst[lst.size - 1].daiTimeInt

        var curInt = startInt
        var curIdx = 0

        while (curInt <= endInt) {

            // 判断curInt 是否在 lst 里面
            //  如果在 则直接取出来
            // 如果不在, 则直接生成一个
            if (lst[curIdx].daiTimeInt == curInt) {
                preTarget = lst[curIdx].target
                finalLst.add(lst[curIdx])
                curIdx++
                curInt = MyTimeUtils.nextDayInt(curInt)
            } else {
                finalLst.add(BsRecord(curInt, preTarget, 0))
                curInt = MyTimeUtils.nextDayInt(curInt)
            }
        }
        return finalLst
    }

}